#include "Metrics.h"
#include "Conversion.h"

//#define USE_REGULAR
#define USE_SUM
//#define USE_MAX
//#define USE_MIN

double Metrics::distance_sum(const Point_d p, const Point_d q)
{
    Kernel_d::Vector_d v = p - q;
    double distance = 0;
    for(int i = 0; i < p.dimension() / 2; ++i)
    {
        double x = v[2*i];
        double y = v[2*i+1];
        distance += sqrt(x*x+y*y);
    }
    return distance;
}

double Metrics::distance_max(const Point_d p, const Point_d q)
{
    Kernel_d::Vector_d v = p - q;
    double max = 0;
    for(int i = 0; i < p.dimension() / 2; ++i)
    {
        double x = v[2*i];
        double y = v[2*i+1];
        double cur = sqrt(x*x+y*y);
        if (cur > max)
        {
            max = cur;
        }
    }
    return max;
}

double Metrics::distance_min(const Point_d p, const Point_d q)
{
    Kernel_d::Vector_d v = p - q;
    double min = -1;
    for(int i = 0; i < p.dimension() / 2; ++i)
    {
        double x = v[2*i];
        double y = v[2*i+1];
        double cur = sqrt(x*x+y*y);
        if ((min < 0) || (cur < min))
        {
            min = cur;
        }
    }
    return min;
}

double Metrics::distance(const Point_d p, const Point_d q)
{
#ifdef USE_REGULAR
    return (p - q).squared_length();
#endif
#ifdef USE_SUM
    return distance_sum(p, q);
#endif
#ifdef USE_MAX
    return distance_max(p, q);
#endif
#ifdef USE_MIN
    return distance_min(p, q);
#endif
}

double Metrics::distance(const Point_2 p , const Point_2 q)
{
    //return (p - q).squared_length().exact().to_double();
    vector<Point_2> a, b;
    a.push_back(p);
    b.push_back(q);
    return distance(Conversion::to_Point_d(a), Conversion::to_Point_d(b));
}

double Metrics::distance(const Point_2_ie p , const Point_2_ie q)
{
    return (p - q).squared_length();
}